package data

import (
	"context"
	"github.com/go-kratos/kratos/v2/errors"
	"github.com/go-kratos/kratos/v2/log"
	"helloworld/internal/biz"
	"helloworld/internal/data/ent/user"
	"helloworld/internal/utils"
	"regexp"
	"time"
)

// data层，与数据库进行直接交互

// 对数据层对象进行封装
type userRepo struct {
	data *Data
	log  *log.Helper
}

// 用户列表
func (u userRepo) ListUsers(ctx context.Context) ([]*biz.Data, error) {
	ps, err := u.data.db.User.Query().All(ctx)
	if err != nil {
		return nil, err
	}
	rv := make([]*biz.Data, 0)
	for _, p := range ps {
		if p.Isdeleted {
			continue
		}
		rv = append(rv, &biz.Data{
			ID:       p.ID,
			Username: p.Username,
			Password: p.Password,
			Email:    p.Email,
			CreateAt: p.CreateTime,
			UpdateAt: p.UpdatedTime,
		})
	}
	return rv, nil
}

// 获取用户信息
func (u userRepo) GetUser(ctx context.Context, id int64) (*biz.Data, error) {
	p, err := u.data.db.User.Get(ctx, id)
	if err != nil {
		return nil, err
	}
	if p == nil {
		return nil, errors.New(400, "BadUserArgument", "提供的用户参数无效")
	}

	return &biz.Data{
		ID:        p.ID,
		Username:  p.Username,
		Email:     p.Email,
		Password:  p.Password,
		CreateAt:  p.CreateTime,
		UpdateAt:  p.UpdatedTime,
		IsDeleted: p.Isdeleted,
	}, nil
}

// 创建用户
func (u userRepo) CreateUser(ctx context.Context, Data *biz.Data) error {
	// 校验用户是否存在
	eml := Data.Email
	exists, err := u.data.db.User.Query().Where(user.Email(eml)).Exist(ctx)
	if err != nil {
		return err
	}
	if exists {
		return errors.New(400, "BadArgument", "提供的参数无效")
	}
	// 存在用户进行创建操作
	// 单向hash加密密码
	hashdedPwd, err := utils.HashPwd(Data.Password)
	if err != nil {
		return err
	}
	_, err = u.data.db.User.
		Create().
		SetUsername(Data.Username).
		SetEmail(Data.Email).
		SetPassword(hashdedPwd).
		Save(ctx)
	return err
}

// 校验用户是否存在
func (u userRepo) CheckExist(ctx context.Context, eml string) error {
	exists, err := u.data.db.User.Query().Where(user.Email(eml)).Exist(ctx)
	if err != nil {
		return err
	}
	if exists {
		return errors.New(400, "BadArgument", "提供的参数无效")
	}
	return nil
}

// 更新用户信息
func (u userRepo) UpdateUser(ctx context.Context, id int64, Data *biz.Data) error {
	eml := Data.Email

	// 开始更改用户信息
	p, err := u.data.db.User.Get(ctx, id)
	if err != nil {
		return err
	}
	// 加密密码
	hashdedPwd, err := utils.HashPwd(Data.Password)
	// 安全过滤
	//  1. 邮箱安全过滤
	emailRegexp := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
	if !emailRegexp.MatchString(eml) {
		return errors.New(400, "BadArgument", "提供的参数无效")
	}
	// 2. 姓名安全过滤
	nameRegexp := regexp.MustCompile(`^[a-zA-Z ]{2,30}$`)
	if !nameRegexp.MatchString(Data.Username) {
		return errors.New(400, "BadArgument", "提供的参数无效")
	}

	if err != nil {
		return err
	}
	_, err = p.Update().
		SetUsername(Data.Username).
		SetEmail(Data.Email).
		SetPassword(hashdedPwd).
		SetUpdatedTime(time.Now()).
		Save(ctx)
	return err
}

// 删除用户信息
func (u userRepo) DeleteUser(ctx context.Context, id int64) error {
	p, err := u.data.db.User.Get(ctx, id)
	if err != nil {
		return err
	}

	_, err = p.Update().
		SetIsdeleted(true).
		Save(ctx)
	return err
}

// 构造器
func NewUserRepo(data *Data, logger log.Logger) biz.DataRepo {
	return &userRepo{
		data: data,
		log:  log.NewHelper(logger),
	}
}
